package ovt;

import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.logging.Logger;

public class TestUploadAndDownload {
	private static Socket interactionsocket;
	private static Socket synchronizesocket;
	private final static Logger logger = Logger
			.getLogger(TestUploadAndDownload.class.getName());

	public TestUploadAndDownload() {
	}

	public static void main(String[] args) {
		try {
			int interactionport = 10000;
			int synchronizeport = 10001;
			interactionsocket = new Socket("127.0.0.1", interactionport);
			synchronizesocket = new Socket("127.0.0.1", synchronizeport);
		} catch (UnknownHostException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
//		new SynchronizeThread(synchronizesocket).start();
		 new InteractionThread(interactionsocket).start();
	}

	static void readAndWrite0(DataInputStream dis, String path, long size)
			throws IOException {
		FileOutputStream os = getFileOS(path);
		readAndWrite(dis, os, size);
		os.close();
	}

	/**
	 * 供保存接口调用
	 * 
	 * @param path
	 *            要保存的文件路径，文件不存在则创建文件
	 * @return fileoutputstream
	 * @throws IOException
	 */
	private static FileOutputStream getFileOS(String path) throws IOException {
		File file = new File(path);
		if (!file.exists()) {
			file.createNewFile();
		}
		return new FileOutputStream(file);
	}

	/**
	 * 具体的保存实现方法
	 * 
	 * @param dis
	 *            输入流
	 * @param os
	 *            写文件
	 * @param size
	 *            文件大小
	 * @throws IOException
	 */
	public static void readAndWrite(DataInputStream dis, FileOutputStream os,
			long size) {
		try {
			byte[] buffer = new byte[512];
			int chip = 512;
			long imgsize = size;
			while (imgsize > 0) {
				if (imgsize < chip)
					chip = (int) imgsize;
				int n = dis.read(buffer, 0, chip);
				if (n == -1)
					return;
				while (n < chip) {
					int temp = dis.read(buffer, n, chip - n);
					n += temp;
				}
				os.write(buffer, 0, chip);
				imgsize -= n;
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
		return;
	}

}

class SynchronizeThread extends Thread {// 客户端上传线程
	private Socket socket;

	public SynchronizeThread(Socket sc) {
		socket = sc;
	}

	public void run() {
		try {
			DataOutputStream dos = new DataOutputStream(
					socket.getOutputStream());
			DataInputStream dis = new DataInputStream(new BufferedInputStream(
					socket.getInputStream()));
			// UploadMaterial(dis,dos,"D:\\ToBeUploaded\\material.xml");
			UploadMaterial(dis, dos, "D:\\ToBeUploaded\\1.jpg");
			UploadMaterial(dis, dos, "D:\\ToBeUploaded\\2.jpg");
			UploadMaterial(dis, dos, "D:\\ToBeUploaded\\3.jpg");
			UploadMaterial(dis, dos, "D:\\ToBeUploaded\\4.jpg");
			UploadMaterial(dis, dos, "D:\\ToBeUploaded\\5.jpg");
			UploadMaterial(dis, dos, "D:\\ToBeUploaded\\6.jpg");
			UploadMaterial(dis, dos, "D:\\ToBeUploaded\\7.jpg");
			UploadMaterial(dis, dos, "D:\\ToBeUploaded\\8.jpg");
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	// 上传素材方法；
	public void UploadMaterial(DataInputStream dis, DataOutputStream dos,
			String filepath) {
		// 指令长度（4字节）+指令+文件名长度（4字节）+文件名+文件长度（4字节）+文件
		try {
			File file = new File(filepath);
			int filenamelength = file.getName().length();
			 int msglength = 4 + "UPLOAD".length() + 4 + filenamelength + 4;
			
			 byte[] msgbyte = new byte[msglength];
			 for (int i = 0; i < 4; i++) {
			 msgbyte[i] = FormatProcessing.int2byte(6)[i];
			 }
			 for (int i = 4; i < 10; i++) {
			 msgbyte[i] = "UPLOAD".getBytes()[i - 4];
			 }
			 for (int i = 10; i < 14; i++) {
			 msgbyte[i] = FormatProcessing.int2byte(filenamelength)[i - 10];
			 }
			 for (int i = 14; i < 14 + file.getName().length(); i++) {
			 msgbyte[i] = file.getName().getBytes()[i - 14];
			 }
			 for (int i = 14 + file.getName().length(); i < msglength; i++) {
			 msgbyte[i] = FormatProcessing.int2byte((int) file.length())[i
			 - 14 - file.getName().length()];
			 }
			 dos.write(msgbyte);
			 dos.flush();
//			dos.write(FormatProcessing.int2byte(6));
//			dos.flush();
//			dos.write("UPLOAD".getBytes());
//			dos.flush();
//			int filelength = (int) file.length();
//			dos.write(FormatProcessing.int2byte(filenamelength));
//			dos.flush();
//			dos.write(file.getName().getBytes());
//			dos.flush();
//			dos.write(FormatProcessing.int2byte(filelength));
//			dos.flush();
			// 发送文件
			int len = -1;
			byte[] buffer = new byte[1024];
			BufferedInputStream buf_in = null;
			buf_in = new BufferedInputStream(new FileInputStream(file));
			while ((len = buf_in.read(buffer, 0, buffer.length)) != -1) {
				dos.write(buffer, 0, len);
			}
			dos.flush();
			buf_in.close();
			// dos.write(";".getBytes());
			// dos.flush();
			byte[] newbyte = new byte[4];
			dis.read(newbyte);
			int reqlength = FormatProcessing.byte2int(newbyte);
			newbyte = new byte[reqlength];
			dis.read(newbyte);
			System.out.println(file.getName() + " status: "
					+ new String(newbyte));
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

}

// 正常交互过程，备份；
class InteractionThread_original extends Thread {// 客户端下载线程
	public Socket socket;

	public InteractionThread_original(Socket sc) {
		socket = sc;
	}

	public void run() {
		try {
			DataOutputStream dos = new DataOutputStream(
					socket.getOutputStream());
			DataInputStream dis = new DataInputStream(new BufferedInputStream(
					socket.getInputStream()));
			getDownloadMaterial(dis, dos,
					"pip\\object\\159_153_526_413_-1_-1.jpg");
			getDownloadMaterial(dis, dos,
					"pip\\object\\175_139_548_452_31_-1.jpg");
			getDownloadMaterial(dis, dos,
					"pip\\object\\205_78_527_468_31_4.jpg");
			getDownloadMaterial(dis, dos,
					"pip\\object\\223_181_777_575_31_-1.jpg");
			getDownloadMaterial(dis, dos,
					"pip\\object\\225_147_796_559_31_7.jpg");
			getDownloadMaterial(dis, dos,
					"pip\\object\\240_244_626_479_31_-1.jpg");
			getDownloadMaterial(dis, dos,
					"pip\\object\\269_93_534_378_31_-1.jpg");
			getDownloadMaterial(dis, dos,
					"pip\\object\\276_196_773_569_31_-1.jpg");
			shareMaterial(dis, dos, "1.jpg,2.jpg;f1,f2,f3,f4");
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public void getDownloadMaterial(DataInputStream dis, DataOutputStream dos,
			String filename) {
		String request = "DOWNLOAD!" + filename + ";";
		try {
			String directoryname = filename
					.substring(0, filename.indexOf("\\"));
			String directory = "D:\\client\\" + directoryname + "\\";

			if (!new File(directory + "mask\\").exists()) {
				new File(directory + "mask\\").mkdirs();
			}
			dos.write(request.getBytes());
			dos.flush();

			byte[] newbyte = new byte[4];
			dis.read(newbyte);
			int length = FormatProcessing.byte2int(newbyte);
			// logger.info(String.valueOf(length));
			newbyte = new byte[length];
			dis.read(newbyte);
			String filenams = new String(newbyte, "GB2312").trim();
			// logger.info(filenams);
			int index1 = filenams.indexOf(" ");
			String imgfilename = filenams.substring(0, index1);
			String maskfilename = filenams.substring(index1 + 1);
			imgfilename = "D:\\client\\" + directoryname + "\\" + imgfilename;
			maskfilename = "D:\\client\\" + directoryname + "\\mask\\"
					+ maskfilename;
			for (int i = 0; i < 2; i++) {
				newbyte = new byte[8];
				dis.read(newbyte);
				long imgsize = FormatProcessing.byte2long(newbyte);
				if (i == 0)
					TestUploadAndDownload.readAndWrite0(dis, imgfilename,
							imgsize);
				if (i == 1)
					TestUploadAndDownload.readAndWrite0(dis, maskfilename,
							imgsize);
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public void shareMaterial(DataInputStream dis, DataOutputStream dos,
			String request) {
		// request = "1.jpg,2.jpg;f1,f2,f3,f4";
		String code = "SHARE!";
		try {
			// 发送指令
			dos.write(code.getBytes());
			dos.flush();
			// 发送消息长度
			int reqlength = request.length();
			dos.write(FormatProcessing.int2byte(reqlength));
			dos.flush();
			// 发送消息
			dos.write(request.getBytes());
			dos.flush();
			System.out.println("1");
			dos.write(";".getBytes());
			dos.flush();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

class InteractionThread extends Thread {// 客户端下载线程
	public Socket socket;

	private final static Logger logger = Logger
			.getLogger(InteractionThread.class.getName());

	public InteractionThread(Socket sc) {
		socket = sc;
	}

	public void run() {
		try {
			DataOutputStream dos = new DataOutputStream(
					socket.getOutputStream());
			DataInputStream dis = new DataInputStream(new BufferedInputStream(
					socket.getInputStream()));
			// checkStage(dis, dos, "1.0");
			// startStage(dis, dos, "D:\\client\\material.xml");
			getDownloadMaterial(dis, dos,
					"pip\\object\\159_153_526_413_-1_-1.jpg");
			getDownloadMaterial(dis, dos,
					"pip\\object\\175_139_548_452_31_-1.jpg");
			getDownloadMaterial(dis, dos,
					"pip\\object\\205_78_527_468_31_4.jpg");
			getDownloadMaterial(dis, dos,
					"pip\\object\\223_181_777_575_31_-1.jpg");
			getDownloadMaterial(dis, dos,
					"pip\\object\\225_147_796_559_31_7.jpg");
			getDownloadMaterial(dis, dos,
					"pip\\object\\240_244_626_479_31_-1.jpg");
			getDownloadMaterial(dis, dos,
					"pip\\object\\269_93_534_378_31_-1.jpg");
			getDownloadMaterial(dis, dos,
					"pip\\object\\276_196_773_569_31_-1.jpg");
			// shareMaterial(dis, dos, "1.jpg,2.jpg;f1,f2,f3,f4");
			// System.out.println(askForThumbnails("pip", "D:\\client\\pip1\\",
			// dos, dis, 1, 12));
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public void checkStage(DataInputStream dis, DataOutputStream dos,
			String version) {
		// 指令长度（4字节）+指令+版本号长度（4字节）+版本号
		int msglength = 8 + 8 + version.length();
		byte[] msgbyte = new byte[msglength];
		for (int i = 0; i < 4; i++) {
			msgbyte[i] = FormatProcessing.int2byte(8)[i];
		}
		for (int i = 4; i < 12; i++) {
			msgbyte[i] = "CHECKXML".getBytes()[i - 4];
		}
		for (int i = 12; i < 16; i++) {
			msgbyte[i] = FormatProcessing.int2byte(version.length())[i - 12];
		}
		for (int i = 16; i < msglength; i++) {
			msgbyte[i] = version.getBytes()[i - 16];
		}
		try {
			dos.write(msgbyte);
			dos.flush();
			byte[] newbyte = new byte[4];
			dis.read(newbyte);
			int xmllength = FormatProcessing.byte2int(newbyte);
			if (xmllength == 0)
				return;
			else {
				TestUploadAndDownload.readAndWrite0(dis,
						"D://client//client.xml", xmllength);
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 进入文件夹
	 * 
	 * @param directory
	 * @param savepath
	 * @param dos
	 * @param dis
	 * @param pageindex
	 * @param pagecount
	 * @return
	 */
	public int askForThumbnails(String directory, String savepath,
			DataOutputStream dos, DataInputStream dis, int pageindex,
			int pagecount) {
		int issaved = 0;
		try {
			// 指令长度（4字节）+指令+目录名长度（4字节）+目录名及第几页，一页有几个
			StringBuilder sb = new StringBuilder(directory).append("+")
					.append(pageindex).append("+").append(pagecount);
			System.out.println(sb.toString());
			String requestmsg = sb.toString();
			int msglength = 4 + "ENTER".length() + 4 + requestmsg.length();
			byte[] newbyte = new byte[msglength];
			for (int i = 0; i < 4; i++) {
				newbyte[i] = FormatProcessing.int2byte("ENTER".length())[i];
			}
			for (int i = 4; i < 9; i++) {
				newbyte[i] = "ENTER".getBytes()[i - 4];
			}
			for (int i = 9; i < 13; i++) {
				newbyte[i] = FormatProcessing.int2byte(requestmsg.length())[i - 9];
			}
			for (int i = 13; i < msglength; i++) {
				newbyte[i] = requestmsg.getBytes()[i - 13];
			}
			dos.write(newbyte);
			dos.flush();

			String savedirectory = savepath + directory + "\\";
			if (!new File(savedirectory).exists()) {
				new File(savedirectory).mkdirs();
			}
			newbyte = new byte[4];
			dis.read(newbyte);
			int filecount = FormatProcessing.byte2int(newbyte);
			for (int i = 0; i < filecount; i++) {
				newbyte = new byte[4];
				dis.read(newbyte);
				int namesize = FormatProcessing.byte2int(newbyte);
				if (namesize <= 0)
					return issaved;
				newbyte = new byte[8];
				dis.read(newbyte);
				long imgsize = FormatProcessing.byte2long(newbyte);
				if (imgsize <= 0)
					return issaved;
				newbyte = new byte[namesize];
				dis.read(newbyte);
				String imgfilename = new String(newbyte, "GB2312").trim();
				imgfilename = savedirectory + imgfilename;
				TestUploadAndDownload.readAndWrite0(dis, imgfilename, imgsize);
				issaved++;
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
		return issaved;
	}

	public void startStage(DataInputStream dis, DataOutputStream dos,
			String xmlfilename) {
		// 指令长度（4字节）+指令+XML文件长度（4字节）+XML文件
		File xmlfile = new File(xmlfilename);
		if (!xmlfile.exists())
			return;
		int msglength = 13;
		byte[] msgbyte = new byte[msglength];
		for (int i = 0; i < 4; i++) {
			msgbyte[i] = FormatProcessing.int2byte(5)[i];
		}
		for (int i = 4; i < 9; i++) {
			msgbyte[i] = "START".getBytes()[i - 4];
		}
		for (int i = 9; i < 13; i++) {
			msgbyte[i] = FormatProcessing.int2byte((int) xmlfile.length())[i - 9];
		}
		try {
			dos.write(msgbyte);
			dos.flush();
			int len = -1;
			byte[] buffer = new byte[1024];
			BufferedInputStream buf_in = null;
			buf_in = new BufferedInputStream(new FileInputStream(xmlfile));
			while ((len = buf_in.read(buffer, 0, buffer.length)) != -1) {
				dos.write(buffer, 0, len);
			}
			dos.flush();
			buf_in.close();
			// 读取返回信息
			byte[] newbyte = new byte[4];
			dis.read(newbyte);
			int retmsglen = FormatProcessing.byte2int(newbyte);
			newbyte = new byte[retmsglen];
			dis.read(newbyte);
			System.out.println("返回信息为:" + new String(newbyte));
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}

	}

	public void getDownloadMaterial(DataInputStream dis, DataOutputStream dos,
			String filename) {
		// 消息封装过程
		// 消息总长度（8字节）+指令长度（4字节）+指令+要下载的文件名长度（4字节）+要下载的文件名
		try {
			String directoryname = filename
					.substring(0, filename.indexOf("\\"));
			String directory = "D:\\client\\" + directoryname + "\\";

			if (!new File(directory + "mask\\").exists()) {
				new File(directory + "mask\\").mkdirs();
			}
			// 发送消息总长度
//			int msglength = 8 + "DOWNLOAD".length() + filename.length();
//			byte[] sendmsg = new byte[msglength];
//			byte[] codelength = FormatProcessing.int2byte("DOWNLOAD".length());
//			for (int i = 0; i < 4; i++) {
//				sendmsg[i] = codelength[i];
//			}
//			for (int i = 4; i < 4 + "DOWNLOAD".length(); i++) {
//				sendmsg[i] = "DOWNLOAD".getBytes()[i - 4];
//			}
//			for (int i = 4 + "DOWNLOAD".length(); i < 8 + "DOWNLOAD".length(); i++) {
//				sendmsg[i] = FormatProcessing.int2byte(filename.length())[i - 12];
//			}
//			for (int i = 8 + "DOWNLOAD".length(); i < msglength; i++) {
//				sendmsg[i] = filename.getBytes()[i - 16];
//			}
//			dos.write(sendmsg);
//			dos.flush();
			// 发送指令长度
			dos.write(FormatProcessing.int2byte("DOWNLOAD".length()), 0, 4);
			// //发送指令
			dos.write("DOWNLOAD".getBytes(), 0, "DOWNLOAD".length());
			// //发送文件名长度
			dos.write(FormatProcessing.int2byte(filename.length()), 0, 4);
			// //发送文件名
			System.out.println("文件名的byte形式为：");
			dos.write(filename.getBytes(), 0, filename.length());
			dos.flush();
			for (int i = 0; i < filename.getBytes().length; i++) {
				System.out.print(filename.getBytes()[i]);
				System.out.print(" ");
			}
			System.out.println();
			System.out.println("请求文件：" + filename + ",请求发送完毕");
			byte[] newbyte = new byte[4];
			dis.read(newbyte);
			int length = FormatProcessing.byte2int(newbyte);
			System.out.println("收到文件名字长度为：" + String.valueOf(length));
			newbyte = new byte[length];
			dis.read(newbyte);
			String filenams = new String(newbyte, "GB2312").trim();
			System.out.println("收到的文件名字为：" + filenams);
			int index1 = filenams.indexOf(" ");
			String imgfilename = filenams.substring(0, index1);
			String maskfilename = filenams.substring(index1 + 1);
			imgfilename = "D:\\client\\" + directoryname + "\\" + imgfilename;
			maskfilename = "D:\\client\\" + directoryname + "\\mask\\"
					+ maskfilename;
			for (int i = 0; i < 2; i++) {
				newbyte = new byte[8];
				dis.read(newbyte);
				long imgsize = FormatProcessing.byte2long(newbyte);
				if (i == 0)
					TestUploadAndDownload.readAndWrite0(dis, imgfilename,
							imgsize);
				if (i == 1)
					TestUploadAndDownload.readAndWrite0(dis, maskfilename,
							imgsize);
			}
			System.out.println("请求文件：" + filename + ",下载完成；");
			System.out.println();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public void shareMaterial(DataInputStream dis, DataOutputStream dos,
			String request) {
		// 指令长度（4字节）+指令+分享消息长度（8字节）+分享消息（包括被分享的素材名称以及好友列表）
		// request = "1.jpg,2.jpg;f1,f2,f3,f4";
		String code = "SHARE";
		try {
			int msglength = 4 + 5 + 4 + request.length();
			byte[] msgbyte = new byte[msglength];
			for (int i = 0; i < 4; i++) {
				msgbyte[i] = FormatProcessing.int2byte(code.length())[i];
			}
			for (int i = 4; i < 4 + code.length(); i++) {
				msgbyte[i] = code.getBytes()[i - 4];
			}
			for (int i = 4 + code.length(); i < 8 + code.length(); i++) {
				msgbyte[i] = FormatProcessing.int2byte(request.length())[i - 4
						- code.length()];
			}
			for (int i = 8 + code.length(); i < msglength; i++) {
				msgbyte[i] = request.getBytes()[i - 8 - code.length()];
			}
			dos.write(msgbyte);
			dos.flush();
			System.out.println("向服务器端发送分享指令结束");
			// //发送指令
			// dos.write(code.getBytes());
			// dos.flush();
			// //发送消息长度
			// int reqlength = request.length();
			// dos.write(FormatProcessing.int2byte(reqlength));
			// dos.flush();
			// //发送消息
			// dos.write(request.getBytes());
			// dos.flush();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 发送结束消息
	 * 
	 * @param dis
	 * @param dos
	 * @param savepath
	 */
	public void senExitSignal(DataInputStream dis, DataOutputStream dos,
			String savepath) {
		// 指令长度（4字节）+指令
		try {
			byte[] msgbyte = new byte[8];
			for (int i = 0; i < 4; i++) {
				msgbyte[i] = FormatProcessing.int2byte(4)[i];
			}
			for (int i = 4; i < 8; i++) {
				msgbyte[i] = "EXIT".getBytes()[i - 4];
			}
			dos.write(msgbyte);
			dos.flush();
			byte[] newbyte = new byte[8];
			dis.read(newbyte);
			long xmlfilesize = FormatProcessing.byte2long(newbyte);
			TestUploadAndDownload.readAndWrite0(dis, savepath, xmlfilesize);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}
